﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
public class SRPLight
{
    
    private Vector4[] _lightColors;
    private Vector4[] _lightDirOrPos;
    private Vector4[] _spotLightDir;
    private Vector4[] _lightAtten;

    static int
            lightColorId = Shader.PropertyToID("_LightColors"),
            lightDirOrPosId = Shader.PropertyToID("_LightDirOrPos"),
            lightCountId = Shader.PropertyToID("_LightCount"),
            lightAttenId = Shader.PropertyToID("_LightAtten"),
            _spotLightDirId = Shader.PropertyToID("_SpotLightDir");


    private int _lightCount;

    private CommandBuffer _cmd;
    
    

    public SRPLight(int s, CommandBuffer c)
    {
        _lightColors = new Vector4[s];
        _lightDirOrPos = new Vector4[s];
        _spotLightDir = new Vector4[s];
        _lightAtten = new Vector4[s];
        _cmd = c;
        _lightCount = 0;

        SumbitToGpu();
    }

    
    public void SetupLight(ref VisibleLight vL)
    {
        _lightColors[_lightCount] = vL.finalColor;
        
        _lightColors[_lightCount] = vL.finalColor;
        if (vL.lightType == LightType.Directional)
        {
            SetupDirLight(ref vL);
        }
        else if (vL.lightType == LightType.Point)
        {
            SetupPointLight(ref vL);
        }
        else if (vL.lightType == LightType.Spot)
        {
            SetupSpotLight(ref vL);
        }
        _lightCount++;
    }

    private void SetupDirLight(ref VisibleLight vL)
    {
        _lightDirOrPos[_lightCount] = -vL.localToWorldMatrix.GetColumn(2);
        _lightAtten[_lightCount].w = 1f;
    }

    private void SetupPointLight(ref VisibleLight vL)
    {
        _lightDirOrPos[_lightCount] = vL.localToWorldMatrix.GetColumn(3);
        _lightAtten[_lightCount].x = 1f/ Mathf.Max(vL.range * vL.range, 0.000001f);
        _lightAtten[_lightCount].w = 1f;
    }

    private void SetupSpotLight(ref VisibleLight vL)
    {
        _lightDirOrPos[_lightCount] = vL.localToWorldMatrix.GetColumn(3);
        _spotLightDir[_lightCount] = -vL.localToWorldMatrix.GetColumn(2);

        float outerRad = Mathf.Deg2Rad * 0.5f * vL.spotAngle;
        float outerCos = Mathf.Cos(outerRad);
        float outerTan = Mathf.Tan(outerRad);
        float innerCos = Mathf.Cos(Mathf.Atan((46f / 64f) * outerTan));
        float angleRange = Mathf.Max(innerCos - outerCos, 0.001f);

        _lightAtten[_lightCount].z = 1 / angleRange;
        _lightAtten[_lightCount].w = -outerCos * _lightAtten[_lightCount].z;
    }

    public void SumbitToGpu()
    {
        if (_cmd == null)
        {
            return;
        }

        _cmd.SetGlobalVectorArray(lightDirOrPosId, _lightDirOrPos);
        _cmd.SetGlobalVectorArray(lightColorId, _lightColors);
        _cmd.SetGlobalVectorArray(lightAttenId, _lightAtten);
        _cmd.SetGlobalVectorArray(_spotLightDirId, _spotLightDir);
        
        _cmd.SetGlobalInt(lightCountId, _lightCount);
        

        _lightCount = 0;
    }


}
